package com.woniuxy.commons.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.commons.annotation.RequirePerms;
import com.woniuxy.commons.service.FeignAuthService;
import com.woniuxy.commons.util.JWTUtil;
import com.woniuxy.commons.util.ResponseResult;
import com.woniuxy.commons.util.ResultStatus;
import com.woniuxy.commons.util.TokenEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 拦截器：handler的方法会拦 静态资源会拦
 */

@Slf4j
@Component
public class PermsInterceptor extends HandlerInterceptorAdapter {

    // 注入auth模块的service对象
    @Lazy  // 延迟注入，用到该对象的时候再注入
    @Resource
    private FeignAuthService feignAuthService;

    // 在handler的方法之前执行
    // 返回值：true 放行   false终止请求
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 判断当前请求是否是访问的方法
        if (handler instanceof HandlerMethod){
            // 说明在调方法
            HandlerMethod handlerMethod = (HandlerMethod)handler;

            // 获取到即将要访问到的方法
            Method method = handlerMethod.getMethod();
            log.info(method.toString());
            log.info("即将访问：" + method.getName());

            // 判断方法上是否有注解
            if (method.isAnnotationPresent(RequirePerms.class)){
                // 有注解，说明访问该方法需要指定的权限
                // 通过注解得到权限信息
                RequirePerms requirePerms = method.getDeclaredAnnotation(RequirePerms.class);
                // 获取权限
                String perms = requirePerms.value();
                //
                log.info("访问该方法需要：" + perms + " 权限");

                // 获取token
                String token = request.getHeader("authorization");

                log.info(token);

                // 对token进行校验
                if (token == null || token.length() == 0 || token.equals("null")){
                    // 本次请求时绕过了网关直接发送到服务器
                    response.setContentType("text/html;charset=utf-8");

                    response.getWriter().write("<h3>垃圾</h3>");

                    return false;
                }

                // 运行到此处说明有token
                if (JWTUtil.verify(token) != TokenEnum.TOKEN_SUCCESS){
                    // 去登录
                    ResponseResult responseResult = new ResponseResult();
                    responseResult.setCode(403);
                    responseResult.setMsg("请登录");
                    responseResult.setStatus(ResultStatus.NO_LOGIN);

                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().write(new ObjectMapper().writeValueAsString(responseResult));

                    return false;
                }

                // 运行到此处说明token合法
                String username = JWTUtil.getUname(token);

                // 发请求进行鉴权
//                Map<String,String> map = new HashMap<>();
//                map.put("username",username);
//                map.put("perms", perms);
                log.info("准备进行鉴权.....");
                ResponseResult responseResult = feignAuthService.hasPerms(username, perms);
                log.info("鉴权完毕.....");

                // 判断结果
                if (!(Boolean) responseResult.getData()){
                    // 没权限
                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().write(new ObjectMapper().writeValueAsString(responseResult));

                    return false;
                }
            }
        }

        // 放行
        return super.preHandle(request, response, handler);
    }
}
